<template>
    <div class="rx-AutoComplete">
        <RxEmpty v-if="readOnly && !curValue"></RxEmpty>
        <input
            v-else
            :disabled="readOnly"
            class="ant-input"
            :class="['rx-autoComplete-'+metadata.field,readOnly?'ant-input-canEdit':'']"
            v-model="curValue"
            :placeholder="placeholder"
            @blur="onBlur"
            @input="onChange"
            @focus="onFocus"
        />
        <div class="rx-options" v-if="show" :style="style">
            <ul>
                <li @click.stop="change(item.label)" v-for="(item,index) in autoOptions">{{ item.label }}</li>
            </ul>
        </div>
    </div>
</template>

<script>
/*
自动完成
 */
import MForm from '../js/MForm'
import FormBase from "../js/FormBase";
import BaseComplex from "../js/BaseComplex";
import Util from '@/js/Util.js'
import {onMounted, onUnmounted} from 'vue';
import RxEmpty from "@/components/RxEmpty"

export default {
    name: "MAutoComplete",
    mixins: [MForm, FormBase, BaseComplex],
    components:{RxEmpty},
    data() {
        return {
            curValue: "",
            autoOptions: [],
            style: {},
            show: false,
        }
    },
    created() {
        // #ifdef H5
        onMounted(() => {
            // 在组件挂载后添加事件监听器
            let self = this;
            document.addEventListener('click', function (event) {
                var target = event.target;
                while (target && target !== this) {
                    if (target.classList.contains('rx-AutoComplete')) {
                        return;
                    }
                    target = target.parentNode;
                }

                // 如果不是 "exclude" 类的元素或其子元素，则执行你的操作
                self.show = false
            });
        });

        onUnmounted(() => {
            // 在组件销毁前移除事件监听器
            document.removeEventListener('click', this.handleOutsideClick);

        });
       // #endif
        /**
         * 初始化数据来源
         */
        this.initDataSource();
        this.init();
        this.$nextTick(() => {
            this.getDivInfo()
        })
    },
    methods: {
        handleOutsideClick(e) {
            this.show = false
        },
        init() {
            if (this.value != undefined && this.value != "") {
                this.updateValue(this.value)
            }
        },
        getDivInfo() {
            //获取屏幕高度
            let windowHeight = uni.getSystemInfoSync().windowHeight;
            // 创建选择器对象
            const query = uni.createSelectorQuery().in(this);
            // 选择.my-div元素
            query.select('.rx-autoComplete-' + this.metadata.field).boundingClientRect(data => {
                if (data) {
                    if (windowHeight / 2 < data.top) {
                        this.style = {
                            'bottom': '2.5rem',
                            'left': '0rem',
                            'width': data.width + 'px'
                        }
                    } else {
                        this.style = {
                            'top': '2.5rem',
                            'left': '0rem',
                            'width': data.width + 'px'
                        }
                    }
                }
            }).exec(); // 执行选择器查询
        },
        setOptions(e) {
            if (!e) {
                return;
            }
            //只读 选项已有无需查询
            if (this.readOnly || (this.autoOptions && this.autoOptions.length > 0)) {
                return;
            }
            let self = this;
            this.initDataSource(function () {
                self.initAutoOptions(self.options)
            });
        },
        initAutoOptions(options) {
            let sourceConfig = this.metadata.options.sourceConfig;
            if (!options || options.length == 0) {
                this.autoOptions = [];
                return;
            }
            let valueSource = this.metadata.options.valueSource;
            if ("script" == valueSource) {
                this.autoOptions = options;
                return;
            }
            let data = options.map(item => {
                if (valueSource == "dic") {
                    if (sourceConfig.formatType == 'label') {
                        return {label: item.label, value: item.label};
                    } else if (sourceConfig.formatType == 'custom') {
                        let newValue = sourceConfig.formatValue.replace(/\$\{value\}/g, item.value).replace(/\$\{label\}/g, item.label)
                        return {label: newValue, value: newValue};
                    } else {
                        return {label: item.value, value: item.value};
                    }
                } else {
                    let value = sourceConfig.formatValue ? sourceConfig.formatValue.replace(/\s+/g, "") : "";
                    let keys = Object.keys(item);
                    for (let i = 0; i < keys.length; i++) {
                        value = value.replace('${' + keys[i] + '}', item[keys[i]]);
                    }
                    return {...item, label: value.trim(), value: value.trim(), disabled: false};
                }
            });
            this.autoOptions = data;
        },
        onChange: Util.debounce(function (val) {
            if (this.curValue) {
                this.curValue = this.curValue.trim();
            }
            this.updateValue(this.curValue);
            this.triggerEmitEvents('change', this.curValue, this.data)
        }, 500),
        onBlur(val) {
            this.triggerEmitEvents('blur', val, this.data)
        },
        onFocus(val) {
            this.show = true
            this.triggerEmitEvents('focus', val, this.data)
        },
        onAllowClear() {
            this.curVal = ''
            this.updateValue('');
        },
        change(name) {
            this.curValue = name
            this.updateValue(this.curValue);
        }
    },
    watch: {
        "options": {
            handler: function (val, olVal) {
                this.initAutoOptions(val);
            }
        },
        "value": {
            handler(v) {
                this.curValue = v;
            },
            deep: true,
            immediate: true
        }
    },
}
</script>

<style scoped>
.rx-AutoComplete {
    position: relative;
}

.rx-options {
    padding: 4px 11px;
    color: rgba(0, 0, 0, .65);
    font-size: 14px;
    background-color: #fff;
    border: 1px solid #d9d9d9;
    border-radius: 4px;
    max-height: 8rem;
    overflow: auto;
    position: absolute;
    z-index: 99;
    box-sizing: border-box;
}
</style>
